﻿// =============================================================================
// TNTTools AttributeInfoMarkedSerializer.cs
// Copyright (c) 2013 TNTTechnologies Inc.
// =============================================================================

#region

using System;
using System.Collections.Generic;
using System.Text;

using TNTTools.Reflection;
using TNTTools.Serialization;
using TNTTools.Serialization.Interfaces;

#endregion

namespace TNTTools{
    /// <summary>
    ///     A specialization that allow the user to markup code with attributes such as [XMLIgnore]
    /// </summary>
    public class AttributeInfoMarkedSerializer : SimpleSerialization{
        private Dictionary<Type, string> elementNames = new Dictionary<Type, string>();

        public AttributeInfoMarkedSerializer(IReflectionPropertyCache reflectionCache)
            : base(reflectionCache){
        }

        public override void WriteElementStart(StringBuilder stringStream, Type sourceType, ObjectInfo objectInfo){
            stringStream.AppendFormat("<{0} ", this.GetCachedElementName(sourceType, objectInfo));
        }

        public override void WriteElementEnd(StringBuilder stringStream, Type sourceType, ObjectInfo objectInfo){
            stringStream.AppendFormat("</{0}>", this.GetCachedElementName(sourceType, objectInfo));
        }

        public override void WriteXmlAttribute(
            StringBuilder stringStream, ReflectiveProperty infoEx, object value, string attributeName){
            if (!infoEx.ClassMarkUpAttributesXml.ContainsIgnore){
                stringStream.Append(' ');
                stringStream.Append(attributeName);
                stringStream.Append('=');
                stringStream.Append('\"');
                stringStream.Append(value);
                stringStream.Append('\"');
                stringStream.Append(' ');
            }

            if (infoEx.IsLastBasicTypeAttribute){
                stringStream.Append('>');
                stringStream.Append(' ');
            }
        }

        private string GetCachedElementName(Type sourceType, ObjectInfo objectInfo){
            string elementName = null;
            if (this.elementNames.ContainsKey(sourceType)){
                elementName = this.elementNames[sourceType];
            } else{
                int start = 0;
                elementName = objectInfo.classAttributes.GetXmlRootAttributeValue(ref start);

                if (elementName.Length == 0){
                    elementName = objectInfo.classAttributes.GetXmlArrayAttributeValue(ref start);
                }

                if (elementName.Length == 0){
                    elementName = sourceType.Name;
                }
                this.elementNames.Add(sourceType, elementName);
            }
            return elementName;
        }
    }
}